package org.dfl.plugin.views.actions;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.dfl.core.data.Token;
import org.dfl.plugin.DflPlugin;
import org.dfl.plugin.views.ViewsManager;
import org.dfl.plugin.views.debug.HistoriesTreeView;
import org.dfl.plugin.views.debug.TokensTreeView;
import org.dfl.plugin.views.debug.model.HistoryTreeElem;
import org.dfl.plugin.views.debug.model.TokenTreeElem;
import org.dfl.plugin.views.debug.model.TreeElem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.actions.ActionDelegate;

/**
 * action that provide deleting data, token or history objects. 
 * It's used in a HistoriesTreeView and TokensTreeView (see mapping in plugin.xml file)
 * @author Piotr Wlodarczyk
 *
 */
public class DeletePropertyAction extends ActionDelegate {
	
	private IStructuredSelection selection = StructuredSelection.EMPTY;

	/* (non-Javadoc)
	 * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
	 */
	public void selectionChanged(IAction action, ISelection sel) {
		if(sel instanceof IStructuredSelection)
			selection = (IStructuredSelection) sel;
		else 
			selection = StructuredSelection.EMPTY;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	@SuppressWarnings("unchecked")
	public void run(IAction action) {
		if(selection.isEmpty()) return;
		Iterator iter = selection.iterator();
		
		Set<HistoryTreeElem> histories = new HashSet<HistoryTreeElem>();
		Set<TokenTreeElem> tokens = new HashSet<TokenTreeElem>();
		Set<TreeElem> elems = new HashSet<TreeElem>();
		
		while(iter.hasNext()){
			Object toDelete = iter.next();
			if(toDelete instanceof TreeElem && ((TreeElem) toDelete).getParent() instanceof TokenTreeElem){
				toDelete = ((TreeElem) toDelete).getParent();
			}
			
			if(toDelete instanceof HistoryTreeElem){
				histories.add((HistoryTreeElem) toDelete);
			}else if(toDelete instanceof TokenTreeElem){
				tokens.add((TokenTreeElem) toDelete);
			}else if(toDelete instanceof TreeElem){
				elems.add((TreeElem) toDelete);
			}
		}
		
		if(!histories.isEmpty()){
			removeHistories(histories);
		}
		if(!tokens.isEmpty()){
			removeTokens(tokens);
		}
		if(!elems.isEmpty()){
			removeTreeElems(elems);
		}
	}

	private void removeTreeElems(Set<TreeElem> toDeleteElems) {
		Set<Object> parents = new HashSet<Object>();
		for(TreeElem toDelete : toDeleteElems){
			parents.add(toDelete.getParent());
			synchronized (DflPlugin.class) {
				toDelete.getParent().removeChild(toDelete);
				toDelete.getParent().update();
				
			}
		}
		for(Object o : parents){
			ViewsManager.refreshViews(o);

		}
	}

	private void removeTokens(Set<TokenTreeElem> toDeleteTokens) {
		HistoriesTreeView historiesTreeView = HistoriesTreeView .getView();
		TokensTreeView tokensTreeView = TokensTreeView.getView();
		
		// place listeners have to be removed before 
		if(historiesTreeView!=null) historiesTreeView.stopListenPlace();
		if(tokensTreeView!=null) tokensTreeView.stopListenPlace();
		
		for(TokenTreeElem toDelete : toDeleteTokens){
			synchronized (DflPlugin.class) {
				toDelete.getPlace().removeToken(toDelete.getToken());
				toDelete.getParent().removeChild(toDelete);
			}	
		}

		// restore place listeners
		if(historiesTreeView!=null) {
			historiesTreeView.startListenPlace();
			historiesTreeView.getCommonViewer().refresh();
		}
		if(tokensTreeView!=null) {
			tokensTreeView.getCommonViewer().refresh();
			tokensTreeView.startListenPlace();
		}
	}

	private void removeHistories(Set<HistoryTreeElem> toDeleteHist) {
		HistoriesTreeView historiesTreeView = HistoriesTreeView .getView();
		TokensTreeView tokensTreeView = TokensTreeView.getView();
		
		if(historiesTreeView!=null) historiesTreeView.stopListenPlace();
		if(tokensTreeView!=null) tokensTreeView.stopListenPlace();
		

		for (HistoryTreeElem toDelete : toDeleteHist) {
			for (Token token : toDelete.getTokens()) {
				synchronized (DflPlugin.class) {
					toDelete.getPlace().removeToken(token);
				}
			}
			toDelete.getParent().removeChild(toDelete);
		}
		
		if(historiesTreeView!=null) {
			historiesTreeView.getCommonViewer().refresh();
			historiesTreeView.startListenPlace();
		}
		if(tokensTreeView!=null){
			tokensTreeView.setHistoryTreeElems(null);
			tokensTreeView.startListenPlace();
		}
	}
}
